/**
 * @file 通用的筛选表单；（SearchForm里边耦合了业务逻辑，所以不能通用）
 * @author 韩志晨
 * @date 2021-01-13
 *  暂时支持类型：DatePicker、RangePicker、Select、Input
 *  支持联动，支持获取数据，服务端搜索，分页
 *
 *  @param config 配置数组
 *  @param selectOptions 设置下拉options
 *  @param initialValues 初始化
 *  @param onOk  成功
 *  @param onReset  重置
 *  @param onItemChange
 *  @param onfetchOptions 获取某个formitem数据
 */

import React, {
    useImperativeHandle,
    useEffect,
    forwardRef,
    useState
} from 'react';
import {
    Form,
    Button,
    Input,
    DatePicker,
    Select,
    Row,
    Col,
    Spin,
    Empty
} from 'antd';
import omit from 'omit.js';
import debounce from 'lodash/debounce';

import popUpContainer from '~/utils/common/popupFix';
import MaxRangePicker from '../MaxRangePicker';

import './index.less';

const {RangePicker} = DatePicker;

const defaultSelectAllOption = {key: '全部', label: '全部'};

const SearchForm = (props, ref) => {
    const {
        form: outForm,
        config,
        selectOptions,
        onOk,
        onReset,
        onItemChange,
        onfetchOptions,
        formItemLayout = {},
        tailLayout = {},
        initialValues,
        noCache,
        loading
    } = props;
    const [inForm] = Form.useForm();
    const [formConfig, setFormConfig] = useState(config);

    // 支持外部传入form对象.
    const form = outForm || inForm;

    useImperativeHandle(ref, () => ({
        formFields: form
    }));

    // 通过key找到匹配的select，给options赋值
    useEffect(() => {
        const newFormConfig = formConfig.map(item => {
            if (item.key === selectOptions.key) {
                item.optionsConfig.options = selectOptions.options || [];
                item.optionsConfig.pager = selectOptions.pager || {};
                item.props.loading = false;
            }

            return item;
        });

        setFormConfig(newFormConfig);
    }, [selectOptions]);

    // 设置formItem 的 loading属性
    const setLoading = (key, bool) => {
        const newFormConfig = formConfig.map(item => {
            if (item.key === key) {
                item.props.loading = bool;
            }

            return item;
        });

        setFormConfig(newFormConfig);
    };

    const getData = item => {
        const {
            key,
            props: {searchKey},
            dependItemKey,
            dependItemValue,
            isGetingMore,
            optionsConfig: {pager, options} = {}
        } = item;

        const fieldsValue = form.getFieldsValue() ?? {};

        onfetchOptions &&
            onfetchOptions({
                key,
                dependItemKey,
                searchKey,
                pager,
                dependItemValue,
                isGetingMore,
                options,
                fieldsValue,
                noCache
            });
    };

    // 获取焦点时请求数据
    const handleFocus = (e, item) => {
        const {
            key,
            optionsConfig: {options},
            dependItemKey
        } = item;
        const dependItemValue =
            dependItemKey && form.getFieldValue(dependItemKey);
        if (noCache) {
            const newFormConfig = formConfig.map(item1 => {
                if (item1.key === key) {
                    item1.optionsConfig.options = [];
                    item1.optionsConfig.pager = {};
                    item1.props.loading = true;
                }

                return item1;
            });
            setFormConfig(newFormConfig);
            // setLoading(key, true);
            getData({...item, dependItemValue});
        } else if (!options?.length) {
            setLoading(key, true);
            getData({...item, dependItemValue});
        }
    };

    // 根据输入搜索
    const handleSearch = debounce((searchKey, item) => {
        const {key, dependItemKey} = item;
        const newFormConfig = formConfig.map(item1 => {
            if (item1.key === key) {
                item1.props.loading = true;
                item1.props.searchKey = searchKey;
                item1.isGetingMore = false;
            }
            return item1;
        });
        setFormConfig(newFormConfig);
        getData(item);
    }, 500);

    // 分页
    const handleSearchMore = (e, item) => {
        const {key} = item;
        const {
            props: {searchKey}
        } = formConfig.filter(item => item.key === key)[0];

        setLoading(key, true);
        item.optionsConfig.pager = {
            ...item.optionsConfig.pager,
            pageNum: ++item.optionsConfig.pager.pageNum
        };

        item.isGetingMore = true;
        getData({...item, searchKey});
    };

    /** select添加全选逻辑 */
    const handleSelect = (e, item) => {
        const selectValue = form.getFieldValue(`${item.key}`);
        const selectAllOption = item?.props?.selectAllOption ?? defaultSelectAllOption;
        if (e === selectAllOption.key) {
            form.setFieldsValue({[`${item.key}`]: e});
        } else if (selectValue.indexOf(selectAllOption.key) > -1) {
            form.setFieldsValue({[`${item.key}`]: e});
        }
    };

    const renderItem = item => {
        const {pageNum = 1, pageSize = 0, count = 0} =
            item.optionsConfig?.pager || {};
        const hasMore = pageNum * pageSize < count;
        const {type, optionsConfig: {options} = {}} = item;
        const notFoundContent = item.props?.loading ? (
            <Spin style={{width: '100%'}} />
        ) : (
            <Empty />
        );
        const selectAll = item?.props?.selectAll;
        const selectAllOption = item?.props?.selectAllOption;
        // 为了避免全选比其他选项先展示出来
        const newOptions =
            selectAll && options?.length > 0
                ? [selectAllOption ? selectAllOption : defaultSelectAllOption, ...options]
                : options;

        const typeMaps = {
            datePicker: <DatePicker {...item.props} />,
            input: <Input {...item.props} />,
            rangePicker: (
                <RangePicker
                    {...item.props}
                    // disabledDate={e => handleDisabledDate(e, item)}
                    // onCalendarChange={e => handleCalendarChange(e, item)}
                    // onOpenChange={open => handleOpenChange(open, item)}
                />
            ),
            maxRangePicker: <MaxRangePicker {...item.props} />,
            select: (
                <Select
                    {...omit(item.props, ['selectAll', 'selectAllOption', 'onValuesChange'])}
                    onSelect={e => handleSelect(e, item)}
                    onFocus={e => handleFocus(e, item)}
                    onSearch={e => handleSearch(e, item)}
                    dropdownRender={menu => (
                        <>
                            {menu}
                            {hasMore && (
                                <div className="hasMoreBox">
                                    <Button
                                        type="link"
                                        onClick={e => handleSearchMore(e, item)}
                                        loading={item.props?.loading}
                                    >
                                        加载更多
                                    </Button>
                                </div>
                            )}
                        </>
                    )}
                    getPopupContainer={popUpContainer}
                    notFoundContent={notFoundContent}
                >
                    {newOptions?.map(option => (
                        <Select.Option key={option.key} {...option}>
                            {option.label}
                        </Select.Option>
                    ))}
                </Select>
            )
        };

        return typeMaps[type];
    };

    const onFinish = fieldsValue => {
        onOk && onOk(fieldsValue);
    };

    const onValuesChange = (item, all) => {
        const operateItem = formConfig.filter(
            configItem => configItem.key === Object.keys(item)[0]
        );
        const {controlItems} = operateItem[0];

        // 改变时，重置被依赖的item
        if (controlItems) {
            form.resetFields(controlItems);
        }

        onItemChange && onItemChange(item, all);
    };

    const handleReset = () => {
        form.resetFields();
        onReset && onReset();
    };

    return (
        <Form
            {...formItemLayout}
            form={form}
            name="register"
            onFinish={onFinish}
            onValuesChange={onValuesChange}
            // scrollToFirstError
            initialValues
            {...omit(props, ['config', 'onFinish', 'onValuesChange'])}
        >
            <Row gutter={24}>
                {formConfig.map(item => (
                    <Col span={item.span || 12} key={item.key}>
                        <Form.Item
                            // key={item.key}
                            name={item.key}
                            {...omit(item, ['key', 'type', 'props'])}
                        >
                            {renderItem(item)}
                        </Form.Item>
                    </Col>
                ))}
            </Row>
            {(onReset || onOk) && (
                <Form.Item style={{textAlign: 'right'}} {...tailLayout}>
                    {onReset && (
                        <Button onClick={handleReset} loading={loading}>
                            重置
                        </Button>
                    )}
                    &nbsp; &nbsp;
                    {onOk && (
                        <Button
                            type="primary"
                            htmlType="submit"
                            loading={loading}
                        >
                            搜索
                        </Button>
                    )}
                </Form.Item>
            )}
        </Form>
    );
};

export default forwardRef(SearchForm);
